﻿using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System;

namespace ComTools.Extensions
{
	/// <summary>
	/// 字符串的扩展
	/// </summary>
	public static class StringExtentions
	{
        #region String的扩展

        /// <summary>
        /// 过滤SQL数据
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ToMSSQLValue(this object obj, string formatDate = "yyyy-MM-dd HH:mm:ss.fff")
        {
            string resultSQL = "";

            if (obj != null)
            {
                switch (obj.GetType().Name)
                {
                    case "DateTime":
                        var date = Convert.ToDateTime(obj).ToString(formatDate);
                        resultSQL = "'" + date.Replace("'", "''") + "'";
                        break;
                    case "String":
                    case "Boolean":
                        resultSQL = "'" + obj.ToString().Replace("'", "''") + "'";
                        break;
                    default:
                        ;
                        resultSQL = obj.ToString();
                        break;
                }
            }
            else
                resultSQL = "null";
            return resultSQL;
        }


        /// <summary>
        /// 替换回车换行符为html换行符
        /// </summary>
        /// <param name="strValue">要替换的字符串</param>
        /// <returns>替换好的内容</returns>
        [MethodImpl(MethodImplOptions.NoInlining)]
		public static string ReplaceEnterToHtmlBR(this string strValue)
		{
			string stringRet;

			if (strValue.IsNullOrEmptyOrWhitespace())
			{
				stringRet = "";
			}
			else
			{
				strValue = strValue.Replace("\r\n", "<br />");
				strValue = strValue.Replace("\n", "<br />");
				stringRet = strValue;
			}
			return stringRet;
		}

		/// <summary>
		/// 替换sql语句中的单引号
		/// </summary>
		/// <param name="strValue">sql</param>
		/// <returns>替换后的结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static string ReplaceQuotesInSQL(this string strValue)
		{
			string stringRet;

			if (strValue == null)
			{
				stringRet = "";
			}
			else
			{
				strValue = strValue.Replace("'", "''");
				stringRet = strValue;
			}
			return stringRet;
		}

		/// <summary>
		/// 移除Html标签
		/// </summary>
		/// <param name="htmlContent">html内容</param>
		/// <returns>替换后的字符串</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static string RemoveHtml(this string htmlContent)
		{
			if (htmlContent.IsNullOrEmptyOrWhitespace()) return string.Empty;
			string regexstr = @"<[^>]*>";
			return Regex.Replace(htmlContent, regexstr, string.Empty, RegexOptions.IgnoreCase);
		}

		/// <summary>
		/// 过滤HTML中的不安全标签
		/// </summary>
		/// <param name="htmlContent"></param>
		/// <returns>处理结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static string RemoveUnsafeHtml(this string htmlContent)
		{
			if (htmlContent.IsNullOrEmptyOrWhitespace()) return string.Empty;
			htmlContent = Regex.Replace(htmlContent, @"(\<|\s+)o([a-z]+\s?=)", "$1$2", RegexOptions.IgnoreCase);
			htmlContent = Regex.Replace(htmlContent, @"(script|frame|form|meta|behavior|style)([\s|:|>])+", "$1.$2", RegexOptions.IgnoreCase);
			return htmlContent;
		}


		/// <summary>
		/// 扩展方法：判断字符串是否是null或者是空字符串或者是空格
		/// </summary>
		/// <param name="strValue">字符串值</param>
		/// <returns>判断结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsNullOrEmptyOrWhitespace(this string strValue)
		{
			return string.IsNullOrEmpty(strValue) || string.IsNullOrWhiteSpace(strValue);
		}

		/// <summary>
		/// 扩展方法：格式化字符串
		/// <para>
		/// 注：如果传入的格式化字符串是空的或者是格式化过程中出现异常，则返回的是传入的格式化字符串
		/// </para>
		/// </summary>
		/// <param name="strValue">格式化字符</param>
		/// <param name="parameters">替换的字符</param>
		/// <returns>格式化的字符串</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static string FormatString(this string strValue, params object[] parameters)
		{
			var ret = strValue;

			try {
				if (strValue.IsNullOrEmptyOrWhitespace())
					return "";
				ret = string.Format(strValue, parameters);
			}
			catch (Exception ex) {
				throw ex;
			}

			return ret;
		}

		/// <summary>
		/// 扩展方法：校验字符串是否是中文
		/// </summary>
		/// <param name="strValue">字符串内容</param>
		/// <returns>校验结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool CheckStringChineseRegex(this string strValue)
		{
			bool ret = false;

			try
			{
				if (Regex.IsMatch(strValue, @"[\u4e00-\u9fbb]+$"))
					ret = true;
			}
			catch (Exception ex)
			{
				throw ex;
			}


			return ret;
		}


		/// <summary>
		/// URL字符串扩展的异步Get请求
		/// </summary>
		/// <param name="url">请求地址</param>
		/// <returns>响应的Json格式字符串</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static async Task<string> GetAsJsonAsync(this string url)
		{
			using (HttpClient httpClient = new HttpClient())
			{
				try
				{
					var response = await httpClient.GetAsync(url, CancellationToken.None);
					response.EnsureSuccessStatusCode();
					var item = await response.Content.ReadAsStringAsync();
					return item;
				}
				catch (Exception e)
				{
					return e.Message;
				}
			}
		}

		/// <summary>尝试将字符串转为指定类型对象</summary>
		/// <typeparam name="T">要转换成的类型</typeparam>
		/// <param name="value">字符串</param>
		/// <param name="defaultValue">默认的值</param>
		/// <returns>解析失败将返回默认值</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static T TryParse<T>(this string value, T defaultValue)
		{
			object result = null;
			if (value.TryParse(typeof(T), out result))
				return (T)result;
			return defaultValue;
		}

		/// <summary>尝试将字符串转为指定类型对象</summary>
		/// <typeparam name="T">要转换成的类型</typeparam>
		/// <param name="value">字符串</param>
		/// <param name="result">解析结果，解析失败将返回类型的默认值</param>
		/// <returns>解析失败将返回null，解析结果通过result获得</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool TryParse<T>(this string value, out T result)
		{
			object returnResult = null;
			if (value.TryParse(typeof(T), out returnResult))
			{
				result = (T)returnResult;
				return true;
			}
			else
			{
				result = default(T);
				return false;
			}
		}

		/// <summary>尝试将字符串转为指定类型对象</summary>
		/// <param name="type">要转换成的类型</param>
		/// <param name="value">字符串</param>
		/// <param name="result">解析结果，解析失败将返回null</param>
		/// <returns>解析失败将返回null，解析结果通过result获得</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool TryParse(this string value, Type type, out object result)
		{
			bool flag = false;

			if (value.IsNullOrEmptyOrWhitespace())
			{
				result = null;
				return flag;
			}

			object obj = null;

			// 校验类型是否是可为空的泛型类型
			if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
				type = type.GetGenericArguments()[0];

			if (type.IsEnum)
			{
				try
				{
					obj = Enum.Parse(type, value, true);
					flag = true;
				}
				catch
				{
					flag = false;
				}
			}
			else if (type == typeof(Guid))
			{
				try
				{
					obj = Guid.Parse(value);
					flag = true;
				}
				catch
				{
					flag = false;
				}
			}
			else
			{
				switch (Type.GetTypeCode(type))
				{
					case TypeCode.Boolean:
						bool boolResult;
						flag = bool.TryParse(value, out boolResult);
						if (flag) obj = boolResult;
						break;

					case TypeCode.SByte:
						sbyte sbyteResult;
						flag = sbyte.TryParse(value, out sbyteResult);
						if (flag) obj = sbyteResult;
						break;

					case TypeCode.Byte:
						byte byteResult;
						flag = byte.TryParse(value, out byteResult);
						if (flag) obj = byteResult;
						break;

					case TypeCode.Int16:
						short shotResult;
						flag = short.TryParse(value, out shotResult);
						if (flag) obj = shotResult;
						break;

					case TypeCode.UInt16:
						ushort ushortResult;
						flag = ushort.TryParse(value, out ushortResult);
						if (flag) obj = ushortResult;
						break;

					case TypeCode.Int32:
						int intResult;
						flag = int.TryParse(value, out intResult);
						if (flag) obj = intResult;
						break;

					case TypeCode.UInt32:
						uint uintResult;
						flag = uint.TryParse(value, out uintResult);
						if (flag) obj = uintResult;
						break;

					case TypeCode.Int64:
						long longResult;
						flag = long.TryParse(value, out longResult);
						if (flag) obj = longResult;
						break;

					case TypeCode.UInt64:
						ulong ulongResult;
						flag = ulong.TryParse(value, out ulongResult);
						if (flag) obj = ulongResult;
						break;

					case TypeCode.Single:
						float floatResult;
						flag = float.TryParse(value, out floatResult);
						if (flag) obj = floatResult;
						break;

					case TypeCode.Double:
						double result11;
						flag = double.TryParse(value, out result11);
						if (flag) obj = result11;
						break;

					case TypeCode.Decimal:
						decimal decimalResult;
						flag = decimal.TryParse(value, out decimalResult);
						if (flag) obj = decimalResult;
						break;

					case TypeCode.DateTime:
						DateTime datetimeResult;
						flag = DateTime.TryParse(value, out datetimeResult);
						if (flag) obj = (object)datetimeResult;
						break;

					case TypeCode.String:
						obj = value;
						flag = true;
						break;
					default:
						break;
				}
			}
			result = obj;
			return flag;
		}

		/// <summary>尝试将字符串转为指定类型对象</summary>
		/// <typeparam name="T">要转换成的类型</typeparam>
		/// <param name="value">字符串</param>
		/// <returns>解析失败将返回默认值</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static T TryParse<T>(this string value)
		{
			return value.TryParse<T>(default(T));
		}
		#endregion

		#region 正则
		/// <summary>
		/// 字母
		/// </summary>
		public const string Alpha = @"^[a-zA-Z]*$";

		/// <summary>
		/// 验证是否是字母
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsAlpha(this string value)
		{
			return Regex.Match(value, Alpha).Success;
		}

		/// <summary>
		/// 大写字母
		/// </summary>
		public const string AlphaUpperCase = @"^[A-Z]*$";

		/// <summary>
		/// 验证是否是大写字母
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsAlphaUpperCase(this string value)
		{
			return Regex.Match(value, AlphaUpperCase).Success;
		}

		/// <summary>
		/// 小写字母
		/// </summary>
		public const string AlphaLowerCase = @"^[a-z]*$";

		/// <summary>
		/// 验证是否是小写字母
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsAlphaLowerCase(this string value)
		{
			return Regex.Match(value, AlphaLowerCase).Success;
		}

		/// <summary>
		/// 字母和数字
		/// </summary>
		public const string AlphaNumeric = @"^[a-zA-Z0-9]*$";

		/// <summary>
		/// 验证是否是字母和数字
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IAlphaNumeric(this string value)
		{
			return Regex.Match(value, AlphaNumeric).Success;
		}

		/// <summary>
		/// 字母和数字还有空格
		/// </summary>
		public const string AlphaNumericSpace = @"^[a-zA-Z0-9 ]*$";

		/// <summary>
		/// 验证是否是字母和数字还有空格
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsAlphaNumericSpace(this string value)
		{
			return Regex.Match(value, AlphaNumericSpace).Success;
		}

		/// <summary>
		/// 字母数字和空格还有横线
		/// </summary>
		public const string AlphaNumericSpaceDash = @"^[a-zA-Z0-9 \-]*$";

		/// <summary>
		/// 验证是否是字母数字和空格还有横线
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsAlphaNumericSpaceDash(this string value)
		{
			return Regex.Match(value, AlphaNumericSpaceDash).Success;
		}

		/// <summary>
		/// 字母数字加空间，破折号和下划线
		/// </summary>
		public const string AlphaNumericSpaceDashUnderscore = @"^[a-zA-Z0-9 \-_]*$";

		/// <summary>
		/// 验证是否是字母数字加空间，破折号和下划线
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsAlphaNumericSpaceDashUnderscore(this string value)
		{
			return Regex.Match(value, AlphaNumericSpaceDashUnderscore).Success;
		}

		/// <summary>
		/// 小数
		/// </summary>
		public const string Numeric = @"^\-?[0-9]*\.?[0-9]*$";

		/// <summary>
		/// 验证是否是小数
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsNumeric(this string value)
		{
			return Regex.Match(value, Numeric).Success;
		}

		/// <summary>
		/// 整数
		/// </summary>
		public const string Integer = @"^\-?[0-9]*$";

		/// <summary>
		/// 验证是否是整数
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsInteger(this string value)
		{
			return Regex.Match(value, Integer).Success;
		}

		/// <summary>
		/// E-mail
		/// </summary>
		public const string Email = @"^([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}$";

		/// <summary>
		/// 验证是否是E-mail
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsEmail(this string value)
		{
			return Regex.Match(value, Email).Success;
		}

		/// <summary>
		/// Url
		/// </summary>
		public const string Url = @"^^(ht|f)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&%\$#_=]*)?$";

		/// <summary>
		/// 验证是否是Url
		/// </summary>
		/// <param name="value">字符串</param>
		/// <returns>验证结果</returns>
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static bool IsUrl(this string value)
		{
			return Regex.Match(value, Url).Success;
		}
		#endregion

		#region 字符串生成内容为StringContent的HttpResponseMessage

		///// <summary>
		///// 创建一个StringContent的HttpResponseMessage
		///// </summary>
		///// <param name="responseStringMessage">包含的响应字符串</param>
		///// <param name="request">当前请求对象</param>
		///// <param name="contentType">响应类型</param>
		///// <param name="status">响应状态</param>
		///// <returns>HttpResponseMessage</returns>
		//public static HttpResponseMessage CreateStringContentResponseMessage(this string responseStringMessage, HttpRequestMessage request, string contentType = "application/json", HttpStatusCode status = HttpStatusCode.OK)
		//{
		//	var response = request.CreateResponse(status);
		//	response.Content = new StringContent(responseStringMessage);
		//	response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
		//	return response;
		//}

		/// <summary>
		///  创建一个html格式的、StringContent的HttpResponseMessage
		/// </summary>
		/// <param name="resultHtml"></param>
		/// <returns></returns>
		public static HttpResponseMessage CreateStringContentResponseMessage(this string resultHtml)
		{
			var response = new HttpResponseMessage(HttpStatusCode.OK);
			response.Content = new StringContent(resultHtml);
			response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
			return response;
		}

		///// <summary>
		///// 创建一个json格式的、StringContent的HttpResponseMessage
		///// </summary>
		///// <typeparam name="T">创建的类型</typeparam>
		///// <param name="t">创建的对象</param>
		///// <param name="request">当前请求对象</param>
		///// <param name="status">响应状态</param>
		///// <returns>HttpResponseMessage</returns>
		//public static HttpResponseMessage CreateJsonStringContentResponseMessage<T>(this T t, HttpRequestMessage request, HttpStatusCode status)
		//{
		//	var response = request.CreateResponse(status);
		//	response.Content = new StringContent(JsonHelper.GetJsonFromObject(t));
		//	response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
		//	return response;
		//}
		#endregion
	}
}
